#include "PokerData.h"
#include <algorithm>
#include <functional>

using std::sort;
using std::greater;

HandPoker::HandPoker(const Poker & one, const Poker & two) {
  this->handPoker = new Poker[2];
  this->handPoker[0] = one;
  this->handPoker[1] = two;
}

HandPoker::~HandPoker() {
  delete [] this->handPoker;
}

const Poker * HandPoker::getHandPoker() const {
  return this->handPoker;
}

bool HandPoker::isFlush() const {
  return this->handPoker[0].suit == this->handPoker[1].suit;
}

string HandPoker::toString() const {
  string result;
  if(this->handPoker[0] > this->handPoker[1]) {
    result.append(this->handPoker[0].toString());
    result.append(this->handPoker[1].toString());
  } else {
    result.append(this->handPoker[1].toString());
    result.append(this->handPoker[0].toString());
  }
  if (isFlush()) {
    result.append("s");
  }
  return result;
}

FlopPoker::FlopPoker(const Poker & one, const Poker & two, const Poker & three) {
  this->flopPoker = new Poker[3];
  this->flopPoker[0] = one;
  this->flopPoker[1] = two;
  this->flopPoker[2] = three;
}

FlopPoker::~FlopPoker() {
  delete [] this->flopPoker;
}

const Poker * FlopPoker::getFlopPoker() const {
  return this->flopPoker;
}

TurnPoker::TurnPoker(const Poker & turnPoker) {
  this->turnPoker = turnPoker;
}

const Poker * TurnPoker::getTurnPoker() const {
  return & turnPoker;
}

RiverPoker::RiverPoker(const Poker & riverPoker) {
  this->riverPoker = riverPoker;
}

const Poker * RiverPoker::getRiverPoker() const {
  return &this->riverPoker;
}

PokerData::PokerData()
: pHandPoker(0)
, pFlopPoker(0)
, pTurnPoker(0)
, pRiverPoker(0){
}

PokerData::~PokerData() {
  delete pHandPoker;
  delete pFlopPoker;
  delete pTurnPoker;
  delete pRiverPoker;
}

void PokerData::setHandPoker(const HandPoker & handPoker) {
  if (pHandPoker) {
    delete pHandPoker;
  }
  const Poker * poker = handPoker.getHandPoker();
  pHandPoker = new HandPoker(poker[0], poker[1]);
}

void PokerData::setFlopPoker(const FlopPoker & flopPoker) {
  if (pFlopPoker) {
    delete pFlopPoker;
  }
  const Poker * poker = flopPoker.getFlopPoker();
  pFlopPoker = new FlopPoker(poker[0], poker[1], poker[2]);
}

void PokerData::setTurnPoker(const TurnPoker & turnPoker) {
  if (pTurnPoker) {
    delete pTurnPoker;
  }
  pTurnPoker = new TurnPoker(*(turnPoker.getTurnPoker()));
}

void PokerData::setRiverPoker(const RiverPoker & riverPoker) {
  if (pRiverPoker) {
    delete pRiverPoker;
  }
  pRiverPoker = new RiverPoker(*(riverPoker.getRiverPoker()));
}

vector<Poker> PokerData::getPokers() const {
  vector<Poker> result;
  if (pHandPoker) {
    const Poker * poker = this->pHandPoker->getHandPoker();
    for (int i = 0; i < HAND_POKER_COUNT; i++){
      result.push_back(*poker++);
    }
  }
  if (pFlopPoker) {
    const Poker * poker = this->pFlopPoker->getFlopPoker();
    for (int i = 0; i < FLOP_POKER_COUNT; i++) {
      result.push_back(*poker++);
    }
  }
  if (pTurnPoker) {
    result.push_back(*(this->pTurnPoker->getTurnPoker()));
  }
  if (pRiverPoker) {
    result.push_back(*(this->pRiverPoker->getRiverPoker()));
  }
  return result;
}

void PokerData::sortData(vector<Poker> & data){
  sort(data.begin(), data.end(), greater<Poker>());
}

vector<Poker> PokerData::getFlushData(vector<Poker> & data) {
  vector<Poker> diamond, club, heart, spade;
  for (int i = 0; i < data.size(); i++) {
    const Poker poker = data.at(i);
    switch(poker.suit) {
      case DIAMOND:
        diamond.push_back(poker);
        break;
      case CLUB:
        club.push_back(poker);
        break;
      case HEART:
        heart.push_back(poker);
        break;
      case SPADE:
        spade.push_back(poker);
        break;
      default:
        break;
    };
  }

  vector<Poker> & result = diamond;
  if (result.size() < club.size()) {
    result = club;
  }
  if (result.size() < heart.size()) {
    result = heart;
  }
  if (result.size() < spade.size()) {
    result = spade;
  }
  return result;
}
